﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace SpeakupBackend
{
    public class DelegateProxy<DelegateType>
    {
        SynchronizationContext SyncContext;

        public DelegateProxy()
        {
            SyncContext = SynchronizationContext.Current;
            if (SyncContext == null)
            {
                SyncContext = new SynchronizationContext();
            }

            if (typeof(DelegateType).IsAssignableFrom(typeof(MulticastDelegate)))
            {
                throw new ArgumentException(String.Format("{0} type is not delegate",typeof(DelegateType)));
            }
        }

        private void Post(Object [] args)
        {
            if (ProxySource == null) return;

            MulticastDelegate proxySourceDelegate = ProxySource as MulticastDelegate;            
            foreach (Delegate d in proxySourceDelegate.GetInvocationList())
            {
                SendOrPostCallback callback = new SendOrPostCallback(delegate(object state)
                {
                    d.DynamicInvoke(args);
                });

                SyncContext.Post(callback, null);
            }
        }

        #region Proxy Consumers 

        public void ProxyConsumer()
        {
            ProxyConsumer(new Object[0] );
        }

        public void ProxyConsumer<T1>(T1 t)
        {
            ProxyConsumer(new Object[] { t });
        }

        public void ProxyConsumer<T1, T2>(T1 _t1, T2 _t2)
        {
            ProxyConsumer(new Object[] { _t1, _t2 });
        }

        public void ProxyConsumer<T1, T2, T3>(T1 _t1, T2 _t2, T3 _t3)
        {
            ProxyConsumer(new Object[] { _t1, _t2, _t3 });
        }

        public void ProxyConsumer<T1, T2, T3, T4>(T1 _t1, T2 _t2, T3 _t3, T4 _t4)
        {
            ProxyConsumer(new Object[] { _t1, _t2, _t3, _t4 });
        }

        public void ProxyConsumer<T1, T2, T3, T4, T5>(T1 _t1, T2 _t2, T3 _t3, T4 _t4, T5 _t5)
        {
            ProxyConsumer(new Object[] { _t1, _t2, _t3, _t4, _t5 });
        }

        public void ProxyConsumer(Object[] args)
        {
            Post(args);
        }

        #endregion

        public DelegateType ProxySource;
    }

}
